home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1986, 1987 Pat Joseph Monardo. All rights reserved.
- * Copying of this file is granted according to the provisions
- * specified in the file COPYING which must accompany this file.
- */
-
-
- /*
- * align.c
- */
-
- #include "tex.h"
- #include "cmds.h"
- #include "heap.h"
- #include "arith.h"
- #include "eq.h"
- #include "eqstack.h"
- #include "hash.h"
- #include "token.h"
- #include "tokenstack.h"
- #include "scan.h"
- #include "evalstack.h"
- #include "box.h"
- #include "pack.h"
- #include "math.h"
- #include "mlisthlist.h"
- #include "error.h"
- #include "align.h"
-
- ptr align_ptr;
-
- ptr cur_align;
- ptr cur_span;
- ptr cur_loop;
- ptr cur_head;
- ptr cur_tail;
-
- push_alignment ()
- {
- ptr p;
-
- p = get_node(ALIGN_STACK_NODE_SIZE);
- link(p) = align_ptr;
- info(p) = cur_align;
- llink(p) = preamble;
- rlink(p) = cur_span;
- mem[p + 2].i = cur_loop;
- mem[p + 3].i = align_state;
- info(p + 4) = cur_head;
- link(p + 4) = cur_tail;
- align_ptr = p;
- cur_head = get_avail();
- }
-
- pop_alignment ()
- {
- ptr p;
-
- free_avail(cur_head);
- p = align_ptr;
- cur_tail = link(p + 4);
- cur_head = info(p + 4);
- align_state = mem[p + 3].i;
- cur_loop = mem[p + 2].i;
- cur_span = rlink(p);
- preamble = llink(p);
- cur_align = info(p);
- align_ptr = link(p);
- free_node(p, ALIGN_STACK_NODE_SIZE);
- }
-
- init_align ()
- {
- ptr p;
- ptr save_cs_ptr;
-
- save_cs_ptr = cur_cs;
- push_alignment();
- align_state = -1000000;
- if (mode == MMODE && (tail != head || incompleat_noad != NULL)) {
- print_err("Improper ");
- print_esc("halign");
- print(" inside $$'s");
- help_display_align();
- error();
- flush_math();
- }
- push_nest();
- if (mode == MMODE) {
- mode = -VMODE;
- prev_depth = nest[nest_ptr - 2].aux_field;
- } else if (mode > 0)
- negate(mode);
- scan_spec();
- new_save_level(ALIGN_GROUP);
- preamble = NULL;
- cur_align = align_head;
- cur_loop = NULL;
- scanner_status = ALIGNING;
- warning_index = save_cs_ptr;
- align_state = -1000000;
- loop {
- link(cur_align) = new_param_glue(TAB_SKIP_CODE);
- cur_align = link(cur_align);
- if (cur_cmd == CAR_RET)
- break;
- p = align_tokens;
- token_link(p) = NULL;
- loop {
- get_preamble_token();
- if (cur_cmd == MAC_PARAM)
- break;
- if (cur_cmd <= CAR_RET &&
- cur_cmd >= TAB_MARK &&
- align_state == -1000000) {
- if (p == align_tokens &&
- cur_loop == NULL &&
- cur_cmd == TAB_MARK) {
- cur_loop = cur_align;
- } else {
- print_err("Missing # inserted in alignment preamble");
- help_preamble_missing();
- back_error();
- break;
- }
- } else if (cur_cmd != SPACER || p != align_tokens) {
- token_link(p) = new_token();
- p = token_link(p);
- token(p) = cur_tok;
- }
- }
- link(cur_align) = new_null_box();
- cur_align = link(cur_align);
- info(cur_align) = end_span;
- width(cur_align) = NULL_FLAG;
- u_part(cur_align) = token_link(align_tokens);
- p = align_tokens;
- token_link(p) = NULL;
- loop {
- get_preamble_token();
- if (cur_cmd <= CAR_RET &&
- cur_cmd >= TAB_MARK &&
- align_state == -1000000)
- break;
- if (cur_cmd == MAC_PARAM) {
- print_err("Only one # is allowed per tab");
- help_preamble_many();
- error();
- continue;
- }
- token_link(p) = new_token();
- p = token_link(p);
- token(p) = cur_tok;
- }
- token_link(p) = new_token();
- p = token_link(p);
- token(p) = END_TEMPLATE_TOKEN;
- v_part(cur_align) = token_link(align_tokens);
- }
- scanner_status = NORMAL;
- new_save_level(ALIGN_GROUP);
- if (every_cr != NULL)
- begin_token_list(every_cr, EVERY_CR_TEXT);
- align_peek();
- }
-
- get_preamble_token ()
- {
- restart:
- get_token();
- while (cur_chr == SPAN_CODE && cur_cmd == TAB_MARK) {
- get_token();
- if (cur_cmd > MAX_COMMAND) {
- expand();
- get_token();
- }
- }
- if (cur_cmd == ASSIGN_GLUE && cur_chr == GLUE_BASE + TAB_SKIP_CODE) {
- scan_optional_equals();
- scan_glue(GLUE_VAL);
- if (global_defs > 0)
- geq_define(GLUE_BASE + TAB_SKIP_CODE, GLUE_REF, (ptr) cur_val);
- else eq_define(GLUE_BASE + TAB_SKIP_CODE, GLUE_REF, (ptr) cur_val);
- goto restart;
- }
- }
-
- align_peek ()
- {
- restart:
- align_state = 1000000;
- get_nbx_token();
- if (cur_cmd == NO_ALIGN) {
- scan_left_brace();
- new_save_level(NO_ALIGN_GROUP);
- if (mode == -VMODE)
- normal_paragraph();
- } else if (cur_cmd == RIGHT_BRACE)
- fin_align();
- else if (cur_cmd == CAR_RET && cur_chr == CR_CR_CODE)
- goto restart;
- else {
- init_row();
- init_col();
- }
- }
-
- init_row()
- {
- push_nest();
- mode = (-HMODE - VMODE) - mode;
- aux = 0;
- tail_append(new_glue(glue_ptr(preamble)));
- subtype(tail) = TAB_SKIP_CODE + 1;
- cur_align = link(preamble);
- cur_tail = cur_head;
- init_span(cur_align);
- }
-
- init_span (p)
- ptr p;
- {
- push_nest();
- if (mode == -HMODE)
- space_factor = 1000;
- else {
- prev_depth = IGNORE_DEPTH;
- normal_paragraph();
- }
- cur_span = p;
- }
-
- init_col ()
- {
- extra_info(cur_align) = cur_cmd;
- if (cur_cmd == OMIT)
- align_state = 0;
- else {
- back_input();
- begin_token_list((ptr) u_part(cur_align), (qword) U_TEMPLATE);
- }
- }
-
- bool
- fin_col ()
- {
- hword n;
- gord o;
- ptr p;
- ptr q;
- ptr r;
- ptr s;
- ptr u;
- scal w;
-
- q = link(cur_align);
- if (cur_align == NULL || q == NULL)
- confusion("endv");
- p = link(q);
- if (p == NULL && extra_info(cur_align) < CR_CODE) {
- if (cur_loop != NULL) {
- link(q) = new_null_box();
- p = link(q);
- info(p) = end_span;
- width(p) = NULL_FLAG;
- cur_loop = link(cur_loop);
- q = align_tokens;
- r = u_part(cur_loop);
- while (r != NULL) {
- token_link(q) = new_token();
- q = token_link(q);
- token(q) = token(r);
- r = token_link(r);
- }
- token_link(q) = NULL;
- u_part(p) = token_link(align_tokens);
- q = align_tokens;
- r = v_part(cur_loop);
- while (r != NULL) {
- token_link(q) = new_token();
- q = token_link(q);
- token(q) = token(r);
- r = token_link(r);
- }
- token_link(q) = NULL;
- v_part(p) = token_link(align_tokens);
- cur_loop = link(cur_loop);
- link(p) = new_glue(glue_ptr(cur_loop));
- } else {
- print_err("Extra alignment tab has been changed to ");
- print_esc("cr");
- help_align_apply();
- extra_info(cur_align) = CR_CODE;
- error();
- }
- }
- if (extra_info(cur_align) != SPAN_CODE) {
- unsave();
- new_save_level(ALIGN_GROUP);
- if (mode == -HMODE) {
- adjust_tail = cur_tail;
- u = hpack(link(head), NATURAL);
- w = width(u);
- cur_tail = adjust_tail;
- adjust_tail = NULL;
- } else {
- u = vpackage(link(head), NATURAL, 0L);
- w = height(u);
- }
- n = MIN_QUARTERWORD;
- if (cur_span != cur_align) {
- q = cur_span;
- do {
- incr(n);
- q = link(link(q));
- } while (q != cur_align);
- if (n > MAX_QUARTERWORD)
- confusion("256 spans");
- q = cur_span;
- while (link(info(q)) < n)
- q = info(q);
- if (link(info(q)) > n) {
- s = get_node(SPAN_NODE_SIZE);
- info(s) = info(q);
- link(s) = n;
- info(q) = s;
- width(s) = w;
- } else if (width(info(q)) < w)
- width(info(q)) = w;
- } else if (w > width(cur_align))
- width(cur_align) = w;
- type(u) = UNSET_NODE;
- span_count(u) = n;
- get_stretch_order();
- glue_order(u) = o;
- glue_stretch(u) = total_stretch[o];
- get_shrink_order();
- glue_sign(u) = o;
- glue_shrink(u) = total_shrink[o];
- pop_nest();
- link(tail) = u;
- tail = u;
- tail_append(new_glue(glue_ptr(link(cur_align))));
- subtype(tail) = TAB_SKIP_CODE + 1;
- if (extra_info(cur_align) >= CR_CODE)
- return TRUE;
- init_span(p);
- }
- align_state = 1000000;
- get_nbx_token();
- cur_align = p;
- init_col();
- return FALSE;
- }
-
- fin_row ()
- {
- ptr p;
-
- if (mode == -HMODE) {
- p = hpack(link(head), NATURAL);
- pop_nest();
- append_to_vlist(p);
- if(cur_head != cur_tail) {
- link(tail) = link(cur_head);
- tail = cur_tail;
- }
- } else {
- p = vpack(link(head), NATURAL);
- pop_nest();
- link(tail) = p;
- tail = p;
- space_factor = 1000;
- }
- type(p) = UNSET_NODE;
- glue_stretch(p) = 0;
- if (every_cr != NULL)
- begin_token_list(every_cr, EVERY_CR_TEXT);
- align_peek();
- }
-
- fin_align ()
- {
- hword n;
- scal o;
- ptr p;
- ptr q;
- ptr r;
- ptr s;
- scal t;
- ptr u;
- ptr v;
- scal w;
- scal rule_save;
-
- if (cur_group != ALIGN_GROUP)
- confusion("align1");
- unsave();
- if (cur_group != ALIGN_GROUP)
- confusion("align0");
- unsave();
- if (nest[nest_ptr - 1].mode_field == MMODE)
- o = display_indent;
- else o = 0;
- q = link(preamble);
- do {
- flush_list((ptr) u_part(q));
- flush_list((ptr) v_part(q));
- p = link(link(q));
- if (width(q) == NULL_FLAG) {
- width(q) = 0;
- r = link(q);
- s = glue_ptr(r);
- if (s != zero_glue) {
- add_glue_ref(zero_glue);
- delete_glue_ref(s);
- glue_ptr(r) = zero_glue;
- }
- }
- if (info(q) != end_span) {
- t = width(q) + width(glue_ptr(link(q)));
- r = info(q);
- s = end_span;
- info(s) = p;
- n = MIN_QUARTERWORD + 1;
- do {
- width(r) -= t;
- u = info(r);
- while (link(r) > n) {
- s = info(s);
- n = link(info(s)) + 1;
- }
- if (link(r) < n) {
- info(r) = info(s);
- info(s) = r;
- decr(link(r));
- s = r;
- } else {
- if (width(r) > width(info(s)))
- width(info(s)) = width(r);
- free_node(r, SPAN_NODE_SIZE);
- }
- r = u;
- } while (r != end_span);
- }
- type(q) = UNSET_NODE;
- span_count(q) = MIN_QUARTERWORD;
- height(q) = 0;
- depth(q) = 0;
- glue_order(q) = NORMAL;
- glue_sign(q) = NORMAL;
- glue_stretch(q) = 0;
- glue_shrink(q) = 0;
- q = p;
- } while (q != NULL);
- save_ptr -= 2;
- pack_begin_line = -mode_line;
- if (mode == -VMODE) {
- rule_save = overfull_rule;
- overfull_rule = 0;
- p = hpack(preamble, saved(1), (int) saved(0));
- overfull_rule = rule_save;
- } else {
- q = link(preamble);
- do {
- height(q) = width(q);
- width(q) = 0;
- q = link(link(q));
- } while (q != NULL);
- p = vpackage(preamble, saved(1), (int) saved(0), MAX_DIMEN);
- q = link(preamble);
- do {
- width(q) = height(q);
- height(q) = 0;
- q = link(link(q));
- } while (q != NULL);
- }
- pack_begin_line = 0;
- for (q = link(head), s = head; q != NULL; s = q, q = link(q)) {/*DIFF*/
- if (type(q) == UNSET_NODE) {
- if (mode == -VMODE) {
- type(q) = HLIST_NODE;
- width(q) = width(p);
- } else {
- type(q) = VLIST_NODE;
- height(q) = height(p);
- }
- glue_order(q) = glue_order(p);
- glue_sign(q) = glue_sign(p);
- glue_set(q) = glue_set(p);
- shift_amount(q) = o;
- r = link(list_ptr(q));
- s = link(list_ptr(p));
- do {
- n = span_count(r);
- t = width(s);
- w = t;
- u = hold_head;
- while (n > MIN_QUARTERWORD) {
- decr(n);
- s = link(s);
- v = glue_ptr(s);
- link(u) = new_glue(v);
- u = link(u);
- subtype(u) = TAB_SKIP_CODE + 1;
- t += width(v);
- if (glue_sign(p) == STRETCHING)
- if (stretch_order(v) == glue_order(p))
- t += round(glue_set(p) * stretch(v));
- else if (glue_sign(p) == SHRINKING)
- if (shrink_order(v) == glue_order(p))
- t -= round(glue_set(p) * shrink(v));
- s = link(s);
- link(u) = new_null_box();
- u = link(u);
- t += width(s);
- if (mode == -VMODE)
- width(u) = width(s);
- else {
- type(u) = VLIST_NODE;
- height(u) = width(s);
- }
- }
- if (mode == -VMODE) {
- height(r) = height(q);
- depth(r) = depth(q);
- if (t == width(r)) {
- glue_sign(r) = NORMAL;
- glue_order(r) = NORMAL;
- glue_set(r) = 0.0;
- } else if (t > width(r)) {
- glue_sign(r) = STRETCHING;
- if (glue_stretch(r) == 0)
- glue_set(r) = 0.0;
- else glue_set(r) =
- (float) (t - width(r)) / glue_stretch(r);
- } else {
- glue_order(r) = glue_sign(r);
- glue_sign(r) = SHRINKING;
- if (glue_shrink(r) == 0)
- glue_set(r) = 0.0;
- else if (glue_order(r) == NORMAL &&
- width(r) - t > glue_shrink(r))
- glue_set(r) = 1.0;
- else glue_set(r) =
- (float)(width(r) - t) / glue_shrink(r);
- }
- width(r) = w;
- type(r) = HLIST_NODE;
- } else {
- width(r) = width(q);
- if (t == height(r)) {
- glue_sign(r) = NORMAL;
- glue_order(r) = NORMAL;
- glue_set(r) = 0.0;
- } else if (t > height(r)) {
- glue_sign(r) = STRETCHING;
- if (glue_stretch(r) == 0)
- glue_set(r) = 0.0;
- else glue_set(r) =
- (float) (t - height(r)) / glue_stretch(r);
- } else {
- glue_order(r) = glue_sign(r);
- glue_sign(r) = SHRINKING;
- if (glue_shrink(r) == 0)
- glue_set(r) = 0.0;
- else if (glue_order(r) == NORMAL &&
- height(r) - t > glue_shrink(r))
- glue_set(r) = 1.0;
- else glue_set(r) =
- (float) (height(r) - t) / glue_shrink(r);
- }
- height(r) = w;
- type(r) = VLIST_NODE;
- }
- shift_amount(r) = 0;
- if (u != hold_head) {
- link(u) = link(r);
- link(r) = link(hold_head);
- r = u;
- }
- r = link(link(r));
- s = link(link(s));
- } while (r != NULL);
- } else if (type(q) == RULE_NODE) {
- if (is_running(width(q)))
- width(q) = width(p);
- if (is_running(height(q)))
- height(q) = height(p);
- if (is_running(depth(q)))
- depth(q) = depth(p);
- if (o != 0) {/*DIFF*/
- r = link(q); link(q) = NULL;/*DIFF*/
- q = hpack(q, NATURAL);/*DIFF*/
- shift_amount(q) = o;/*DIFF*/
- link(q) = r; link(s) = q;/*DIFF*/
- }
- }
- }
- flush_node_list(p);
- pop_alignment();
- t = aux;
- p = link(head);
- q = tail;
- pop_nest();
- if (mode == MMODE) {
- do_assignments();
- if (cur_cmd != MATH_SHIFT) {
- print_err("Missing $$ inserted");
- help_display_align();
- back_error();
- } else {
- get_x_token();
- if (cur_cmd != MATH_SHIFT) {
- print_err("Display math should end with $$");
- help_display();
- back_error();
- }
- }
- pop_nest();
- tail_append(new_penalty(pre_display_penalty));
- tail_append(new_param_glue(ABOVE_DISPLAY_SKIP_CODE));
- link(tail) = p;
- if (p != NULL)
- tail = q;
- tail_append(new_penalty(post_display_penalty));
- tail_append(new_param_glue(BELOW_DISPLAY_SKIP_CODE));
- prev_depth = t;
- resume_after_display();
- } else {
- aux = t;
- link(tail) = p;
- if (p != NULL)
- tail = q;
- if (mode == VMODE)
- build_page();
- }
- }
-
- /*
- * Help text
- */
-
- help_display_align ()
- {
- help3("Displays can use special alignments (like \\eqalignno)",
- "only if nothing but the alignment itself is between $$'s.",
- "So I've deleted the formulas that preceded this alignment.");
- }
-
- help_preamble_missing ()
- {
- help3("There should be exactly one # between &'s, when an",
- "\\halign or \\valign is being set up. In this case you had",
- "none, so I've put one in; maybe that will work.");
- }
-
- help_preamble_many ()
- {
- help3("There should be exactly one # between &'s, when an",
- "\\halign or \\valign is being set up. In this case you had",
- "more than one, so I'm ignoring all but the first.");
- }
-
- help_align_apply ()
- {
- help3("You have given more \\span or & marks than there were",
- "in the preamble to the \\halign or \\valign now in progress.",
- "So I'll assume that you meant to type \\cr instead.");
- }
-
- help_display ()
- {
- help2("The `$' that I just saw supposedly matches a previous `$$'.",
- "So I shall assume that you typed `$$' both times.");
- }
-